home *** CD-ROM | disk | FTP | other *** search
/ The Utilities Experience / The Utilities Experience - Volume 1.iso / software / misc / o-z / x-windows / mesa-amiwin / src / copypix.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-30  |  15.6 KB  |  574 lines

  1. /* copypix.c */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995  Brian Paul  (brianp@ssec.wisc.edu)
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25. $Id: copypix.c,v 1.17 1995/11/03 17:40:29 brianp Exp $
  26.  
  27. $Log: copypix.c,v $
  28.  * Revision 1.17  1995/11/03  17:40:29  brianp
  29.  * fixed a varname typo, removed unused variables
  30.  *
  31.  * Revision 1.16  1995/10/19  15:47:12  brianp
  32.  * added gamma support
  33.  *
  34.  * Revision 1.15  1995/10/16  15:25:49  brianp
  35.  * added zooming for stencil drawing/copying
  36.  *
  37.  * Revision 1.14  1995/10/14  16:28:21  brianp
  38.  * added glPixelZoom support
  39.  *
  40.  * Revision 1.13  1995/09/15  18:43:25  brianp
  41.  * broke gl_copypixels into sub-functions
  42.  * directly access DD.write_color_span under the right conditions
  43.  *
  44.  * Revision 1.12  1995/09/07  14:15:52  brianp
  45.  * use CC.NewState convention
  46.  * use DEFARRAY macro for MacIntosh support
  47.  *
  48.  * Revision 1.11  1995/08/04  13:07:28  brianp
  49.  * changed some types involved in scale and bias operation
  50.  *
  51.  * Revision 1.10  1995/07/24  19:00:17  brianp
  52.  * convert real window coords to ints with rounding, not truncating
  53.  * changed calls to CLAMP() to prevent type warnings on Suns
  54.  *
  55.  * Revision 1.9  1995/06/12  15:52:07  brianp
  56.  * renamed from copypixels.c to copypix.c
  57.  *
  58.  * Revision 1.8  1995/06/12  15:38:01  brianp
  59.  * changed color arrays to GLubyte
  60.  * added feedback and selection support
  61.  *
  62.  * Revision 1.7  1995/05/31  14:58:45  brianp
  63.  * check for valid rasterpos, use gl_read_color|index_span()
  64.  *
  65.  * Revision 1.6  1995/05/22  21:02:41  brianp
  66.  * Release 1.2
  67.  *
  68.  * Revision 1.5  1995/05/12  19:24:13  brianp
  69.  * replaced CC.Mode!=0 with INSIDE_BEGIN_END
  70.  *
  71.  * Revision 1.4  1995/04/18  15:47:59  brianp
  72.  * added a cast to prevent warning on Suns
  73.  *
  74.  * Revision 1.3  1995/03/13  20:54:53  brianp
  75.  * added read buffer logic
  76.  *
  77.  * Revision 1.2  1995/03/04  19:29:44  brianp
  78.  * 1.1 beta revision
  79.  *
  80.  * Revision 1.1  1995/02/24  14:20:20  brianp
  81.  * Initial revision
  82.  *
  83.  */
  84.  
  85.  
  86. #include <string.h>
  87. #include "context.h"
  88. #include "dd.h"
  89. #include "depth.h"
  90. #include "feedback.h"
  91. #include "gamma.h"
  92. #include "list.h"
  93. #include "macros.h"
  94. #include "pixel.h"
  95. #include "span.h"
  96. #include "stencil.h"
  97.  
  98.  
  99. #ifndef NULL
  100. #  define NULL 0
  101. #endif
  102.  
  103.  
  104.  
  105.  
  106. static void copy_rgb_pixels( GLint srcx, GLint srcy, GLint width, GLint height,
  107.                              GLint destx, GLint desty )
  108. {
  109.    DEFARRAY( GLint, idepth, MAX_WIDTH );
  110.    DEFARRAY( GLubyte, red, MAX_WIDTH );
  111.    DEFARRAY( GLubyte, green, MAX_WIDTH );
  112.    DEFARRAY( GLubyte, blue, MAX_WIDTH );
  113.    DEFARRAY( GLubyte, alpha, MAX_WIDTH );
  114.    GLboolean scale_or_bias, quick_draw, zoom;
  115.    GLint sy, dy, stepy;
  116.    GLint i, j;
  117.    GLboolean setbuffer;
  118.    GLuint gamma_bit;
  119.  
  120.    if (CC.Pixel.ZoomX==1.0F && CC.Pixel.ZoomY==1.0F) {
  121.       zoom = GL_FALSE;
  122.    }
  123.    else {
  124.       zoom = GL_TRUE;
  125.    }
  126.  
  127.    /* Determine if copy should be done bottom-to-top or top-to-bottom */
  128.    if (srcy<desty) {
  129.       /* top-down  max-to-min */
  130.       sy = srcy + height - 1;
  131.       dy = desty + height - 1;
  132.       stepy = -1;
  133.    }
  134.    else {
  135.       /* bottom-up  min-to-max */
  136.       sy = srcy;
  137.       dy = desty;
  138.       stepy = 1;
  139.    }
  140.  
  141.    scale_or_bias = CC.Pixel.RedScale!=1.0 || CC.Pixel.RedBias!=0.0
  142.                 || CC.Pixel.GreenScale!=1.0 || CC.Pixel.GreenBias!=0.0
  143.         || CC.Pixel.BlueScale!=1.0 || CC.Pixel.BlueBias!=0.0
  144.         || CC.Pixel.AlphaScale!=1.0 || CC.Pixel.AlphaBias!=0.0;
  145.  
  146.    if (CC.Depth.Test) {
  147.       /* fill in array of z values */
  148.       GLint z = (GLint) (CC.Current.RasterPos[2] * MAX_DEPTH);
  149.       for (i=0;i<width;i++) {
  150.          idepth[i] = z;
  151.       }
  152.    }
  153.  
  154.    /* temporarily disable gamma correction */
  155.    gamma_bit = CC.RasterMask & GAMMA_BIT;
  156.    CC.RasterMask &= ~GAMMA_BIT;
  157.  
  158.    if (CC.RasterMask==0 && destx>=0 && destx+width<=CC.BufferWidth && !zoom) {
  159.       quick_draw = GL_TRUE;
  160.    }
  161.    else {
  162.       quick_draw = GL_FALSE;
  163.    }
  164.  
  165.    /* If read and draw buffer are different we must do buffer switching */
  166.    setbuffer = CC.Pixel.ReadBuffer!=CC.Color.DrawBuffer;
  167.  
  168.    for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
  169.       /* read */
  170.  
  171.       if (setbuffer) {
  172.          (*DD.set_buffer)( CC.Pixel.ReadBuffer );
  173.       }
  174.       gl_read_color_span( width, srcx, sy, red, green, blue, alpha );
  175.  
  176.       if (scale_or_bias) {
  177.          GLfloat rbias = CC.Pixel.RedBias   * CC.RedScale;
  178.          GLfloat gbias = CC.Pixel.GreenBias * CC.GreenScale;
  179.          GLfloat bbias = CC.Pixel.BlueBias  * CC.BlueScale;
  180.          GLfloat abias = CC.Pixel.AlphaBias * CC.AlphaScale;
  181.          GLint rmax = (GLint) CC.RedScale;
  182.          GLint gmax = (GLint) CC.GreenScale;
  183.          GLint bmax = (GLint) CC.BlueScale;
  184.          GLint amax = (GLint) CC.AlphaScale;
  185.          for (i=0;i<width;i++) {
  186.             GLint r = red[i]   * CC.Pixel.RedScale   + rbias;
  187.             GLint g = green[i] * CC.Pixel.GreenScale + gbias;
  188.             GLint b = blue[i]  * CC.Pixel.BlueScale  + bbias;
  189.             GLint a = alpha[i] * CC.Pixel.AlphaScale + abias;
  190.             red[i]   = CLAMP( r, 0, rmax );
  191.             green[i] = CLAMP( g, 0, gmax );
  192.             blue[i]  = CLAMP( b, 0, bmax );
  193.             alpha[i] = CLAMP( a, 0, amax );
  194.          }
  195.       }
  196.  
  197.       if (CC.Pixel.MapColorFlag) {
  198.          GLfloat r = (CC.Pixel.MapRtoRsize-1) / CC.RedScale;
  199.          GLfloat g = (CC.Pixel.MapGtoGsize-1) / CC.GreenScale;
  200.          GLfloat b = (CC.Pixel.MapBtoBsize-1) / CC.BlueScale;
  201.          GLfloat a = (CC.Pixel.MapAtoAsize-1) / CC.AlphaScale;
  202.          for (i=0;i<width;i++) {
  203.             GLint ir = red[i] * r;
  204.             GLint ig = green[i] * g;
  205.             GLint ib = blue[i] * b;
  206.             GLint ia = alpha[i] * a;
  207.             red[i]   = (GLint) (CC.Pixel.MapRtoR[ir] * CC.RedScale);
  208.             green[i] = (GLint) (CC.Pixel.MapGtoG[ig] * CC.GreenScale);
  209.             blue[i]  = (GLint) (CC.Pixel.MapBtoB[ib] * CC.BlueScale);
  210.             alpha[i] = (GLint) (CC.Pixel.MapAtoA[ia] * CC.AlphaScale);
  211.          }
  212.       }
  213.  
  214.       /* write */
  215.       if (setbuffer) {
  216.          (*DD.set_buffer)( CC.Color.DrawBuffer );
  217.       }
  218.       if (quick_draw && dy>=0 && dy<CC.BufferHeight) {
  219.          (*DD.write_color_span)( width, destx, dy,
  220.                                  red, green, blue, alpha, NULL);
  221.       }
  222.       else if (zoom) {
  223.          gl_write_zoomed_color_span( width, destx, dy, idepth,
  224.                                      red, green, blue, alpha, desty );
  225.       }
  226.       else {
  227.          gl_write_color_span( width, destx, dy, idepth,
  228.                               red, green, blue, alpha, GL_BITMAP );
  229.       }
  230.    }
  231.    UNDEFARRAY( idepth );
  232.    UNDEFARRAY( red );
  233.    UNDEFARRAY( green );
  234.    UNDEFARRAY( blue );
  235.    UNDEFARRAY( alpha );
  236.  
  237.    /* re-enable gamma correction */
  238.    CC.RasterMask |= gamma_bit;
  239. }
  240.  
  241.  
  242.  
  243. static void copy_ci_pixels( GLint srcx, GLint srcy, GLint width, GLint height,
  244.                              GLint destx, GLint desty )
  245. {
  246.    GLint idepth[MAX_WIDTH];
  247.    GLuint indx[MAX_WIDTH];
  248.    GLint sy, dy, stepy;
  249.    GLint i, j;
  250.    GLboolean setbuffer, zoom;
  251.  
  252.    if (CC.Pixel.ZoomX==1.0F && CC.Pixel.ZoomY==1.0F) {
  253.       zoom = GL_FALSE;
  254.    }
  255.    else {
  256.       zoom = GL_TRUE;
  257.    }
  258.  
  259.    /* Determine if copy should be bottom-to-top or top-to-bottom */
  260.    if (srcy<desty) {
  261.       /* top-down  max-to-min */
  262.       sy = srcy + height - 1;
  263.       dy = desty + height - 1;
  264.       stepy = -1;
  265.    }
  266.    else {
  267.       /* bottom-up  min-to-max */
  268.       sy = srcy;
  269.       dy = desty;
  270.       stepy = 1;
  271.    }
  272.  
  273.    if (CC.Depth.Test) {
  274.       /* fill in array of z values */
  275.       GLint z = (GLint) (CC.Current.RasterPos[2] * MAX_DEPTH);
  276.       for (i=0;i<width;i++) {
  277.          idepth[i] = z;
  278.       }
  279.    }
  280.  
  281.    /* If read and draw buffer are different we must do buffer switching */
  282.    setbuffer = CC.Pixel.ReadBuffer!=CC.Color.DrawBuffer;
  283.  
  284.    for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
  285.       /* read */
  286.       if (setbuffer) {
  287.          (*DD.set_buffer)( CC.Pixel.ReadBuffer );
  288.       }
  289.       gl_read_index_span( width, srcx, sy, indx );
  290.  
  291.       /* shift, offset */
  292.       if (CC.Pixel.IndexShift || CC.Pixel.IndexOffset) {
  293.          if (CC.Pixel.IndexShift<0) {
  294.             for (i=0;i<width;i++) {
  295.                indx[i] = (indx[i] >> -CC.Pixel.IndexShift)
  296.                          + CC.Pixel.IndexOffset;
  297.             }
  298.          }
  299.          else {
  300.             for (i=0;i<width;i++) {
  301.                indx[i] = (indx[i] << CC.Pixel.IndexShift)
  302.                          + CC.Pixel.IndexOffset;
  303.             }
  304.          }
  305.       }
  306.  
  307.       /* mapping */
  308.       if (CC.Pixel.MapColorFlag) {
  309.          for (i=0;i<width;i++) {
  310.             if (indx[i] < CC.Pixel.MapItoIsize) {
  311.                indx[i] = CC.Pixel.MapItoI[ indx[i] ];
  312.             }
  313.          }
  314.       }
  315.  
  316.       /* write */
  317.       if (setbuffer) {
  318.          (*DD.set_buffer)( CC.Color.DrawBuffer );
  319.       }
  320.       if (zoom) {
  321.          gl_write_zoomed_index_span( width, destx, dy, idepth, indx, desty );
  322.       }
  323.       else {
  324.          gl_write_index_span( width, destx, dy, idepth, indx, GL_BITMAP );
  325.       }
  326.    }
  327. }
  328.  
  329.  
  330.  
  331. static void copy_depth_pixels( GLint srcx, GLint srcy,
  332.                                GLint width, GLint height,
  333.                                GLint destx, GLint desty )
  334. {
  335.    GLfloat depth[MAX_WIDTH];
  336.    GLint idepth[MAX_WIDTH];
  337.    GLuint indx[MAX_WIDTH];
  338.    GLubyte red[MAX_WIDTH], green[MAX_WIDTH];
  339.    GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];
  340.    GLint sy, dy, stepy;
  341.    GLint i, j;
  342.    GLboolean zoom;
  343.  
  344.    if (!CC.DepthBuffer) {
  345.       gl_error( GL_INVALID_OPERATION, "glCopyPixels" );
  346.       return;
  347.    }
  348.  
  349.    if (CC.Pixel.ZoomX==1.0F && CC.Pixel.ZoomY==1.0F) {
  350.       zoom = GL_FALSE;
  351.    }
  352.    else {
  353.       zoom = GL_TRUE;
  354.    }
  355.  
  356.    /* Determine if copy should be bottom-to-top or top-to-bottom */
  357.    if (srcy<desty) {
  358.       /* top-down  max-to-min */
  359.       sy = srcy + height - 1;
  360.       dy = desty + height - 1;
  361.       stepy = -1;
  362.    }
  363.    else {
  364.       /* bottom-up  min-to-max */
  365.       sy = srcy;
  366.       dy = desty;
  367.       stepy = 1;
  368.    }
  369.  
  370.    /* setup colors or indexes */
  371.    if (CC.RGBAflag) {
  372.       GLubyte r, g, b, a;
  373.       r = (GLint) (CC.Current.Color[0] * CC.RedScale);
  374.       g = (GLint) (CC.Current.Color[1] * CC.GreenScale);
  375.       b = (GLint) (CC.Current.Color[2] * CC.BlueScale);
  376.       a = (GLint) (CC.Current.Color[3] * CC.AlphaScale);
  377.       if (CC.RasterMask & GAMMA_BIT) {
  378.          gl_apply_gamma( 1, &r, &g, &b );
  379.       }
  380.       MEMSET( red,   (int) r, width );
  381.       MEMSET( green, (int) g, width );
  382.       MEMSET( blue,  (int) b, width );
  383.       MEMSET( alpha, (int) a, width );
  384.    }
  385.    else {
  386.       for (i=0;i<width;i++) {
  387.          indx[i] = CC.Current.Index;
  388.       }
  389.    }
  390.  
  391.    for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
  392.       /* read */
  393.       gl_read_depth_span( width, srcx, sy, depth );
  394.       /* scale, bias, clamp */
  395.       for (i=0;i<width;i++) {
  396.          GLfloat d = depth[i] * CC.Pixel.DepthScale + CC.Pixel.DepthBias;
  397.          idepth[i] = (GLint) (CLAMP( d, 0.0, 1.0 ) * MAX_DEPTH);
  398.       }
  399.       /* write */
  400.       if (CC.RGBAflag) {
  401.          if (zoom) {
  402.             gl_write_zoomed_color_span( width, destx, dy, idepth,
  403.                                         red, green, blue, alpha, desty );
  404.          }
  405.          else {
  406.             gl_write_color_span( width, destx, dy, idepth,
  407.                                  red, green, blue, alpha, GL_BITMAP );
  408.          }
  409.       }
  410.       else {
  411.          if (zoom) {
  412.             gl_write_zoomed_index_span( width, destx, dy, idepth, indx, desty);
  413.          }
  414.          else {
  415.             gl_write_index_span( width, destx, dy, idepth, indx, GL_BITMAP );
  416.          }
  417.       }
  418.    }
  419. }
  420.  
  421.  
  422.  
  423. static void copy_stencil_pixels( GLint srcx, GLint srcy,
  424.                                  GLint width, GLint height,
  425.                                  GLint destx, GLint desty )
  426. {
  427.    GLubyte stencil[MAX_WIDTH];
  428.    GLint sy, dy, stepy;
  429.    GLint i, j;
  430.    GLboolean zoom;
  431.  
  432.    if (!CC.StencilBuffer) {
  433.       gl_error( GL_INVALID_OPERATION, "glCopyPixels" );
  434.       return;
  435.    }
  436.  
  437.    if (CC.Pixel.ZoomX==1.0F && CC.Pixel.ZoomY==1.0F) {
  438.       zoom = GL_FALSE;
  439.    }
  440.    else {
  441.       zoom = GL_TRUE;
  442.    }
  443.  
  444.    /* Determine if copy should be bottom-to-top or top-to-bottom */
  445.    if (srcy<desty) {
  446.       /* top-down  max-to-min */
  447.       sy = srcy + height - 1;
  448.       dy = desty + height - 1;
  449.       stepy = -1;
  450.    }
  451.    else {
  452.       /* bottom-up  min-to-max */
  453.       sy = srcy;
  454.       dy = desty;
  455.       stepy = 1;
  456.    }
  457.  
  458.    for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
  459.       /* read */
  460.       gl_read_stencil_span( width, srcx, sy, stencil );
  461.       /* shift, offset */
  462.       if (CC.Pixel.IndexShift<0) {
  463.          for (i=0;i<width;i++) {
  464.             stencil[i] = (stencil[i] >> -CC.Pixel.IndexShift)
  465.                          + CC.Pixel.IndexOffset;
  466.          }
  467.       }
  468.       else {
  469.          for (i=0;i<width;i++) {
  470.             stencil[i] = (stencil[i] << CC.Pixel.IndexShift)
  471.              + CC.Pixel.IndexOffset;
  472.          }
  473.       }
  474.       /* mapping */
  475.       if (CC.Pixel.MapStencilFlag) {
  476.          for (i=0;i<width;i++) {
  477.             if ((GLint) stencil[i] < CC.Pixel.MapStoSsize) {
  478.                stencil[i] = CC.Pixel.MapStoS[ stencil[i] ];
  479.             }
  480.          }
  481.       }
  482.       /* write */
  483.       if (zoom) {
  484.          gl_write_zoomed_stencil_span( width, destx, dy, stencil, desty );
  485.       }
  486.       else {
  487.          gl_write_stencil_span( width, destx, dy, stencil );
  488.       }
  489.    }
  490. }
  491.  
  492.  
  493.  
  494.  
  495. void gl_copypixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height,
  496.             GLenum type )
  497. {
  498.    GLint destx, desty;
  499.  
  500.    if (INSIDE_BEGIN_END) {
  501.       gl_error( GL_INVALID_OPERATION, "glCopyPixels" );
  502.       return;
  503.    }
  504.  
  505.    if (width<0 || height<0) {
  506.       gl_error( GL_INVALID_VALUE, "glCopyPixels" );
  507.       return;
  508.    }
  509.  
  510.    if (CC.NewState) {
  511.       gl_update_state();
  512.    }
  513.  
  514.    if (CC.RenderMode==GL_RENDER) {
  515.       /* Destination of copy: */
  516.       if (!CC.Current.RasterPosValid) {
  517.      return;
  518.       }
  519.       destx = (GLint) (CC.Current.RasterPos[0] + 0.5F);
  520.       desty = (GLint) (CC.Current.RasterPos[1] + 0.5F);
  521.  
  522.       if (type==GL_COLOR && CC.RGBAflag) {
  523.          copy_rgb_pixels( srcx, srcy, width, height, destx, desty );
  524.       }
  525.       else if (type==GL_COLOR && !CC.RGBAflag) {
  526.          copy_ci_pixels( srcx, srcy, width, height, destx, desty );
  527.       }
  528.       else if (type==GL_DEPTH) {
  529.          copy_depth_pixels( srcx, srcy, width, height, destx, desty );
  530.       }
  531.       else if (type==GL_STENCIL) {
  532.          copy_stencil_pixels( srcx, srcy, width, height, destx, desty );
  533.       }
  534.       else {
  535.      gl_error( GL_INVALID_ENUM, "glCopyPixels" );
  536.       }
  537.    }
  538.    else if (CC.RenderMode==GL_FEEDBACK) {
  539.       APPEND_TOKEN( (GLfloat) GL_COPY_PIXEL_TOKEN );
  540.       gl_feedback_vertex( CC.Current.RasterPos[0],
  541.               CC.Current.RasterPos[1],
  542.               CC.Current.RasterPos[2],
  543.               CC.Current.RasterPos[3],
  544.               CC.Current.Color, CC.Current.Index,
  545.               CC.Current.TexCoord );
  546.    }
  547.    else if (CC.RenderMode==GL_SELECT) {
  548.       /* TODO: verify that this is correct */
  549.       CC.HitFlag = GL_TRUE;
  550.       if (CC.Current.RasterPos[2] < CC.HitMinZ) {
  551.      CC.HitMinZ = CC.Current.RasterPos[2];
  552.       }
  553.       if (CC.Current.RasterPos[2] > CC.HitMaxZ) {
  554.      CC.HitMaxZ = CC.Current.RasterPos[2];
  555.       }
  556.    }
  557.  
  558. }
  559.  
  560.  
  561.  
  562. void glCopyPixels( GLint x, GLint y, GLsizei width, GLsizei height,
  563.            GLenum type )
  564. {
  565.    if (CC.CompileFlag) {
  566.       gl_save_copypixels( x, y, width, height, type );
  567.    }
  568.    if (CC.ExecuteFlag) {
  569.       gl_copypixels( x, y, width, height, type );
  570.    }
  571. }
  572.  
  573.  
  574.